using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;

namespace ZYFramework.ObjectPool
{
    public partial class Com_ObjectPolicy<T> : IObjectPolicy<T>
    {
        #region 创建销毁

        /// <summary>
        /// 同步创建函数
        /// </summary>
        private readonly Func<T> _creationFunc_Sync;

        /// <summary>
        /// 异步创建函数
        /// </summary>
        private readonly Func<CancellationToken, UniTask<T>> _creationFunc_Async;

        /// <summary>
        /// 同步激活函数
        /// </summary>
        private readonly Action<T> _activationFunc_Sync;

        /// <summary>
        /// 异步激活函数
        /// </summary>
        private readonly Func<T, CancellationToken, UniTask> _activationFunc_Async;

        /// <summary>
        /// 同步销毁函数
        /// </summary>
        private readonly Action<T> _destroyFunc_Sync;

        /// <summary>
        /// 异步销毁函数
        /// </summary>
        private readonly Func<T, CancellationToken, UniTask> _destroyFunc_Async;

        #endregion

        #region 回收

        /// <summary>
        /// 同步回收函数
        /// </summary>
        private readonly Action<T> _recycleFunc_Sync;

        /// <summary>
        /// 异步回收函数
        /// </summary>
        private readonly Func<T, CancellationToken, UniTask> _recycleFunc_Async;

        #endregion
    }
    public partial class Com_ObjectPolicy<T>
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="creationFunc">同步创建函数</param>
        /// <param name="creationFuncAsync">异步创建函数</param>
        /// <param name="activationFunc">同步激活函数</param>
        /// <param name="activationFuncAsync">异步激活函数</param>
        /// <param name="destroyFunc">同步销毁函数</param>
        /// <param name="destroyFuncAsync">异步销毁函数</param>
        public Com_ObjectPolicy(
            Func<T> creationFunc_Sync = null,
            Func<CancellationToken, UniTask<T>> creationFunc_Async = null,
            Action<T> activationFunc = null,
            Func<T, CancellationToken, UniTask> activationFunc_Async = null,
            Action<T> destroyFunc_Sync = null,
            Func<T, CancellationToken, UniTask> destroyFunc_Async = null,
            Action<T> recycleFunc_Sync = null,
            Func<T, CancellationToken, UniTask> recycleFunc_Async = null)
        {
            _creationFunc_Sync = creationFunc_Sync;
            _creationFunc_Async = creationFunc_Async;
            _activationFunc_Sync = activationFunc;
            _activationFunc_Async = activationFunc_Async;
            _destroyFunc_Sync = destroyFunc_Sync;
            _destroyFunc_Async = destroyFunc_Async;
            _recycleFunc_Sync = recycleFunc_Sync;
            _recycleFunc_Async = recycleFunc_Async;
        }
        #region 创建销毁
        public T Create_Sync()
        {
            T obj = _creationFunc_Sync();

            // 如果对象实现了IPoolable接口，调用Create_Sync进行初始化
            if (obj is IPoolable poolable)
            {
                poolable?.Create_Sync();
            }

            return obj;
        }

        public async UniTask<T> Create_Async(CancellationToken cancellationToken = default)
        {
            T obj;

            if (_creationFunc_Async != null)
            {
                obj = await _creationFunc_Async(cancellationToken);
            }
            else
            {
                // 警告：异步创建方法回退到同步创建，可能影响异步性能优势
                // 建议配置 CreationFuncAsync 以获得真正的异步创建性能
                Debug.LogWarning($"[Create_Async<{typeof(T).Name}>] 没有挂载异步创建函数，但是异步流程，回退到调用同步创建函数，但是可能影响异步性能");
                obj = _creationFunc_Sync();
            }

            // 如果对象实现了IPoolable接口，调用Create_Sync进行初始化
            if (obj is IPoolable poolable)
            {
                poolable?.Create_Sync();
            }

            return obj;
        }

        public void Activate_Sync(T obj)
        {
            _activationFunc_Sync?.Invoke(obj);

            // 如果对象实现了IPoolable接口，调用OnGet
            if (obj is IPoolable poolable)
            {
                poolable?.Activate_Sync();
            }
        }

        public async UniTask Activate_Async(T obj, CancellationToken cancellationToken = default)
        {
            if (_activationFunc_Async != null)
            {
                await _activationFunc_Async(obj, cancellationToken);
            }
            else
            {
                Activate_Sync(obj);

                return;
            }

            // 如果对象实现了IPoolable接口，调用OnGetAsync
            if (obj is IPoolable asyncPoolable)
            {
                asyncPoolable?.Activate_Sync();
            }
        }

        public void Destroy_Sync(T obj)
        {
            // 如果对象实现了IPoolable接口，调用OnDestroy
            if (obj is IPoolable poolable)
            {
                poolable?.OnDestroy_Sync();
            }

            _destroyFunc_Sync?.Invoke(obj);
        }

        public async UniTask Destroy_Async(T obj, CancellationToken cancellationToken = default)
        {
            // 如果对象实现了IAsyncPoolable接口，调用OnDestroyAsync
            if (obj is IPoolable asyncPoolable)
            {
                asyncPoolable?.OnDestroy_Sync();
            }

            if (_destroyFunc_Async != null)
            {
                await _destroyFunc_Async(obj, cancellationToken);
            }
            else
            {
                Destroy_Sync(obj);
            }
        }
        #endregion

        #region 回收

        public void Recycle_Sync(T obj)
        {
            // 如果对象实现了IPoolable接口，调用OnReturn
            if (obj is IPoolable poolable)
            {
                poolable?.OnRelease_Sync();
            }

            _recycleFunc_Sync?.Invoke(obj);
        }

        public async UniTask Recycle_Async(T obj, CancellationToken cancellationToken = default)
        {
            // 如果对象实现了IAsyncPoolable接口，调用OnReturnAsync
            if (obj is IPoolable asyncPoolable)
            {
                asyncPoolable?.OnRelease_Sync();
            }

            if (_recycleFunc_Async != null)
            {
                await _recycleFunc_Async(obj, cancellationToken);
            }
            else
            {
                Recycle_Sync(obj);
                return;
            }
        }

        #endregion
    }
}